
import logging
import os
import shutil
import subprocess
import sys
import time
from contextlib import contextmanager

from ocup.constants import DNF_TRANSACTION_ERR

logger = logging.getLogger("ocup")


def touch(file):
    with open(file, "w") as _:
        pass


def cp_r(src, dst):
    shutil.copytree(src, dst)


def rm_rf(f):
    if os.path.isfile(f):
        os.remove(f)
    else:
        shutil.rmtree(f)


def rebuild_db():
    result = subprocess.run(["/usr/bin/rpmdb", "--rebuilddb"])
    if result.returncode:
        logger.error("rebuild db failed")


def fix_db_path(root="/"):
    new_rpmdb_path = os.path.join(root, "/usr/lib/sysimage/rpm")
    old_rpmdb_path = os.path.join(root, "/var/lib/rpm")
    if os.path.exists(old_rpmdb_path):
        if os.path.exists(new_rpmdb_path):
            os.rename(new_rpmdb_path, "{}_{}".format(new_rpmdb_path, time.time()))
        cp_r(old_rpmdb_path, new_rpmdb_path)


def fix_db_macro():
    config = "/usr/lib/rpm/macros"
    try:
        with open(config) as f:
            lines = f.readlines()
        for i, line in enumerate(lines):
            if line.startswith('%_dbpath'):
                lines[i] = '%_dbpath\t\t%{_usr}/lib/sysimage/rpm\n'
                break
        with open(config, 'w') as f:
            f.write("".join(lines))
    except IOError as e:
        logger.error(e)
        raise e


def notify_upgrade():
    msg = "The os is upgrading..."
    notify(msg)


def notify_success():
    msg = "Upgrade OpenCloud OS success\nPlease reboot the machine to boot OpenCloud OS 9"
    notify(msg)


def notify(msg):
    cmd = ["/usr/bin/wall", "-n", msg]
    try:
        subprocess.run(cmd)
    except Exception as e:
        # Not important
        logger.debug(e)


def is_efi():
    return os.path.exists("/sys/firmware/efi")


@contextmanager
def redirect_err():
    current_stderr = sys.stderr
    try:
        sys.stderr = open(DNF_TRANSACTION_ERR, 'a')
    except Exception as e:
        logger.error(e)
        sys.stderr = current_stderr
    try:
        yield
    except Exception as e:
        raise e
    finally:
        try:
            sys.stderr.close()
        except Exception:
            pass
        try:
            sys.stderr = current_stderr
        except Exception:
            pass
